﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Common;
using System.Data;

namespace BusinessPlatform.Core.Database
{
    internal abstract class Database : IDatabase
    {
        #region Private Variable
        private string _ConnString;
        private DbProviderFactory _dbProviderFactory;
        private DbConnection _Connection;
        private DbTransaction _Transaction;
        #endregion
        #region Properties
        /// <summary>
        /// 数据库
        /// </summary>
        public string DbName { get; set; }
        /// <summary>
        /// 数据驱动连接字符串
        /// </summary>
        public string ConnString
        {
            get { return _ConnString; }
            set { _ConnString = value; }
        }
        /// <summary>
        /// 数据源
        /// </summary>
        public DbProviderFactory dbProviderFactory
        {
            get { return _dbProviderFactory; }
            set { _dbProviderFactory = value; }
        }
        public DbConnection Connection
        {
            get { return _Connection; }
        }
        public DbTransaction Transaction
        {
            get { return _Transaction; }
        }
        #endregion
        #region Contractor
        /// <summary>
        /// 读取配置文件数据源驱动字符串创建数据库实例
        /// </summary>
        protected Database()
        {
            ConnString = ConnectionString.ToString;
            dbProviderFactory = ConnectionString.dbProviderFactory;
        }
        /// <summary>
        /// 权限指定的字符串创建数据库实例
        /// </summary>
        /// <param name="iConnectionString"></param>
        protected Database(string iConnectionString)
        {
            ConnString = iConnectionString;
            dbProviderFactory = ConnectionString.dbProviderFactory;
        }
        #endregion
        #region Methods
        #region Connection
        /// <summary>
        /// 打开连接
        /// </summary>
        /// <returns></returns>
        public virtual void OpenConnection()
        {
            DbConnection Connection = dbProviderFactory.CreateConnection();
            Connection.ConnectionString = ConnString;
            try
            {
                if (Connection.State != ConnectionState.Open)
                {
                    Connection.Open();
                    this._Connection = Connection;
                }
            }
            catch (Exception ex)
            {
                if (Connection != null)
                    Connection.Close();
                throw (ex);
            }
        }
        /// <summary>
        /// 关闭连接
        /// </summary>
        public virtual void CloseConnection()
        {
            if (Transaction == null)
                if (Connection.State != ConnectionState.Closed)
                    Connection.Close();
        }
        #endregion
        #region Transaction
        /// <summary>
        /// 启动事务
        /// </summary>
        public virtual void BeginTransaction()
        {
            if (Connection == null)
                OpenConnection();
            if (Connection.State != ConnectionState.Closed)
                this._Transaction = Connection.BeginTransaction();
        }
        /// <summary>
        /// 提示事务
        /// </summary>
        /// <param name="TransOpt"></param>
        public virtual void EndTranscation(TransactionOptions TransOpt)
        {
            if (Transaction == null) return;
            if (TransOpt == TransactionOptions.Commit)
                Transaction.Commit();
            else
                Transaction.Rollback();
            this._Transaction = null;
            if (Connection != null)
                CloseConnection();
        }
        #endregion
        #region Parameter
        /// <summary>
        /// 构建参数名称
        /// </summary>
        /// <param name="ParameterName"></param>
        /// <returns></returns>
        protected virtual string BuilderParameterName(string ParameterName)
        {
            return ParameterName;
        }
        /// <summary>
        /// 获取DbParameter对象
        /// </summary>
        /// <param name="ParameterName"></param>
        /// <returns></returns>
        private DbParameter CreateDbParameter(string ParameterName)
        {
            DbParameter dbParameter = dbProviderFactory.CreateParameter();
            dbParameter.ParameterName = BuilderParameterName(ParameterName);
            return dbParameter;
        }
        public virtual DbParameter AddParameter(string ParameterName, DbType dbType, object Value)
        {
            return AddParameter(ParameterName, dbType, Value, 0, ParameterDirection.Input, string.Empty, DataRowVersion.Default);
        }
        /// <summary>
        /// 获取添加参数
        /// </summary>
        /// <returns></returns>
        public virtual DbParameter AddParameter(string ParameterName, DbType dbType, object Value, int Size, ParameterDirection Direction, string SourceColumn, DataRowVersion SourceVersion)
        {
            var dbParameter = CreateDbParameter(ParameterName);
            dbParameter.DbType = dbType;
            dbParameter.Size = Size;
            dbParameter.Direction = Direction;
            dbParameter.Value = Value ?? DBNull.Value;
            dbParameter.SourceColumn = SourceColumn;
            dbParameter.SourceVersion = SourceVersion;
            return dbParameter;
        }
        #endregion
        #region DbCommand
        /// <summary>
        /// 返回对数据源执行的SQL语句和存储过程。
        /// </summary>
        /// <param name="QueryText"></param>
        /// <param name="DbParameters"></param>
        /// <returns></returns>
        private DbCommand CreateDbCommand(String QueryText, IList<DbParameter> DbParameters)
        {
            if (Connection == null)
                OpenConnection();
            DbCommand Command = dbProviderFactory.CreateCommand();
            Command.Connection = Connection;
            if (Transaction != null)
                Command.Transaction = Transaction;
            Command.CommandType = CommandType.Text;
            Command.CommandText = QueryText;
            foreach (DbParameter Parameter in DbParameters)
            {
                Command.Parameters.Add(Parameter);
            }
            return Command;
        }
        /// <summary>
        /// 获取Command对象
        /// </summary>
        /// <param name="QueryText"></param>
        /// <returns></returns>
        private DbCommand CreateDbCommand(String QueryText)
        {
            return CreateDbCommand(QueryText, new List<DbParameter>());
        }
        #endregion
        #region ExceuteNonQuery
        /// <summary>
        /// 对连接对象执行SQL语句
        /// </summary>
        /// <param name="QueryText">T-SQL语句</param>
        /// <param name="dbParameters">参数列表</param>
        /// <returns></returns>
        public virtual int ExceuteNonQuery(String QueryText, IList<DbParameter> dbParameters)
        {
            DbCommand Command = CreateDbCommand(QueryText);
            foreach (DbParameter dbParameter in dbParameters)
            {
                Command.Parameters.Add(dbParameter);
            }
            return Command.ExecuteNonQuery();
        }
        /// <summary>
        /// 对连接对象执行SQL语句
        /// </summary>
        /// <param name="QueryText">T-SQL语句</param>
        /// <returns></returns>
        public virtual int ExceuteNonQuery(String QueryText)
        {
            return ExceuteNonQuery(QueryText, new List<DbParameter>());
        }
        #endregion ExceuteNonQuery
        #region ExceuteScalar
        /// <summary>
        /// 
        /// </summary>
        /// <param name="QueryText"></param>
        /// <returns></returns>
        public virtual object ExceuteScalar(String QueryText)
        {
            return ExceuteScalar(QueryText, new List<DbParameter>());
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="QueryText"></param>
        /// <param name="dbParameters"></param>
        /// <returns></returns>
        public virtual object ExceuteScalar(string QueryText, IList<DbParameter> dbParameters)
        {
            DbCommand Command = CreateDbCommand(QueryText);
            foreach (DbParameter dbParameter in dbParameters)
            {
                Command.Parameters.Add(dbParameter);
            }
            object result = Command.ExecuteScalar();
            CloseConnection();
            return result;
        }
        #endregion
        #region ExceuteDataReader
        public virtual IDataReader ExceuteReader(string QueryText, IList<DbParameter> dbParameters)
        {
            DbCommand Command = CreateDbCommand(QueryText, dbParameters);
            var DataReader = Command.ExecuteReader();
            //CloseConnection();
            return DataReader;
        }
        public virtual IDataReader ExceuteReader(string QueryText)
        {
            return ExceuteReader(QueryText, new List<DbParameter>());
        }
        #endregion
        #endregion

        public void Dispose()
        {
            GC.Collect();
        }
    }

}
